﻿using System;
using System.Collections.Generic;
using System.Linq;
//using System.Threading;
using System.Web;
using DrillOnline.Hubs;
using Microsoft.AspNet.SignalR;
using DocumentFormat.OpenXml.Office.Excel;
using System.Web.Mvc;
using System.Security.Principal;
using DrillOnline.Models;
using DrillOnline.Services.Scenarios;


namespace DrillOnline.Services
{
    public class DrillServices
    {
        public Models.SiteDbEntities DB { get; set; }
        public IPrincipal SiteUser { get; set; }
        public Controllers._BaseController ControllerContext { get; set; }
        public const string DEFAULTKEY = "default";

        public void UnloadScenarios()
        {
            if (ScenariosHost.Instance.Sessions.Count > 1)
            {
                foreach (var item in ScenariosHost.Instance.Sessions)
                {
                    item.Value.Dispose();
                }
                ScenariosHost.Instance.Sessions.Clear();
            }

        }
        public DrillScenarios LoadScenarios(DrillSubject m)
        {
            //create a scenarios. with key=guid, and add to host;

            //create a sessionmodel from subject,with key, and save to db;
            //load subject

            //测试时只支持一个剧情，name is default
            var key = Guid.NewGuid();
            var keystr = key.ToString();

            if (ScenariosHost.Instance.Sessions.Count > 1)
            {
                foreach (var item in ScenariosHost.Instance.Sessions)
                {
                    item.Value.Dispose();
                }
                ScenariosHost.Instance.Sessions.Clear();
                throw new ArgumentOutOfRangeException("同时只允许运行一个演练,已经清理现有数据。");

            }

            DrillScenarios ds = null;


            if (ScenariosHost.Instance.Sessions.ContainsKey("default"))
            {
                ds = ScenariosHost.Instance.Sessions["default"] as DrillScenarios;
                ds.Timeline.Stop();
                ds.Dispose();
                ScenariosHost.Instance.Sessions.Clear();
                ds = null;
            }

            ds = new DrillScenarios();
            //ds.SessionKey = keystr;
            ds.Subject = m;
            ds.SessionKey = "default";
            ds.SessionName = DateTime.Now.ToString("yyyy年MM月dd日HH点 ") + m.Title + " 演练";

            ds.SceneList = LoadDrillSubjectEvents(m);

            //以后角色组/角色就已经定义在剧情里了。有了剧情就有了角色组了
            //测试时，有两个组 GroupA B
            Scenarios.ActorGroup tempag = null;

            ds.ActorGroups = m.ActorGroups.Select(v => new Scenarios.ActorGroup
        {
            ID = v.Id,
            Model = v,
            GroupKey = v.Title,
            Actors = (v.DefaultActors == null) ? (new List<Actor>()) : (v.DefaultActors.Split(',').Select(j => new Actor() { ActorKey = j, Password = v.DefaultPwd, GroupKey = v.Title }).ToList()),
            Examiners = (v.DefaultExaminers == null) ? (new List<Actor>()) : (v.DefaultExaminers.Split(',').Select(j => new Actor() { ActorKey = j, Password = v.DefaultExaminerPwd, GroupKey = v.Title }).ToList()),
        }).ToList();
            ds.ActorGroups.ForEach(v=>v.Actors.ForEach(j=>j.Group=v));
            ds.ActorGroups.ForEach(v => v.Examiners.ForEach(j => j.Group = v));
            //剧情的起始年代也就已经定了
            ds.Timeline.StoryBaseTime = m.StoryBaseTime;
            ds.Timeline.Config_PlayingTimeRate = (int)m.PlayingRate;
            ds.Timeline.Config_TickerInterval = 2000;

            ScenariosHost.Instance.Sessions.Add(DEFAULTKEY, ds);
            return ds;

        }
        List<DrillScene> LoadDrillSubjectEvents(DrillSubject m)
        {
            List<string> errors = new List<string>();
            List<DrillScene> sl = new List<DrillScene>();
            foreach (var ev in m.DrillSubjectEvents.OrderBy(v => v.OffsetSec))
            {
                try
                {
                    sl.Add(new DrillScene()
                    {
                        Model = ev,
                        Offset = ev.OffsetSec,
                        Title = ev.Title,
                        Groups = ev.TargetGroup.Split(',')
                    });
                }
                catch (Exception ex)
                {
                    errors.Add(ev.OffsetSec.ToString());
                }
            }
            if (errors.Count > 0)
            {
                throw new ArgumentException("以下事件解析式发生错误，请处理。[" + string.Join(",", errors.ToArray()) + "]");
            }
            else
            {
                return sl;
            }
        }


    }
}